/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package fi.uba.algo3.tp3.modelo.actores;

import fi.uba.algo3.tp3.modelo.notificaciones.StateNotification;
import fi.uba.algo3.tp3.modelo.servicios.ServicioJuego;
import fi.uba.algo3.tp3.vista.Observador;

/**
 *
 * @author ariel
 */
public class EstadoFantasma {

    private Fantasma fantasma;
    private Estado estado;



    // Visibilidad Del Paquete
    public enum Estado {

        COMIDO, ATACANDO, HUYENDO, ENJAULADO
    }

    // Visibilidad del paquete
    EstadoFantasma(Fantasma fantasma) {
        this.fantasma = fantasma;
        this.estado = Estado.ENJAULADO;
    }

    public void manejarEstado(ServicioJuego servicio) {
        switch (estado) {
            case ATACANDO:
                atacando(servicio);
                break;
            case COMIDO:
                comido(servicio);
                break;
            case HUYENDO:
                huyendo(servicio);
                break;
            case ENJAULADO:
                enjaulado(servicio);
                break;
        }
    }

    private void enjaulado(ServicioJuego servicio) {
        if (!servicio.obtenerJaula().hayColision(fantasma)) {
            actualizarEstado(Estado.ATACANDO);
        } else {
            fantasma.vivirEnJaula();
        }
    }

    void reestablecer() {
        actualizarEstado(Estado.ENJAULADO);
    }

    void actualizarEstado(Estado estado) {
        this.estado = estado;
    }

    // Visibilidad del paquete solamente
    void intentarAtacar(Observador observer) throws NoSePuedeAtacarException {
        if (!puedoCambiarEstado(Estado.ATACANDO, Estado.HUYENDO, observer)) {
            throw new NoSePuedeAtacarException("No Se Puede Atacar");
        }
    }

    // Visibilidad del paquete solamente
    void intentarHuir(Observador observer) throws NoSePuedeHuirException {
        if (!puedoCambiarEstado(Estado.HUYENDO, Estado.ATACANDO, observer)) {
            throw new NoSePuedeHuirException("No Se Puede Huir");
        }
    }

    // Visibilidad del paquete solamente
    void intenterComido(Observador observer) throws NoSePuedeComidoException {
        if (!puedoCambiarEstado(Estado.COMIDO, Estado.HUYENDO, observer)) {
            throw new NoSePuedeComidoException("No Se Puede Estar Comido");
        }
    }
//    // Visibilidad del paquete solamente

    void intentarEnjaular(Observador observer) throws NoSePuedeEnjaularException {
        // si se dan esas condiciones tiro excepcion
        if (fantasma.estoyEnPosicionInicial()) {
            if (!puedoCambiarEstado(Estado.ENJAULADO, Estado.COMIDO, observer)) {
                throw new NoSePuedeEnjaularException("No Se Puede Estar Enjaulado");
            }
        } else {
            throw new NoSePuedeEnjaularException("No Se Puede Estar Enjaulado");
        }

    }

    EstadoFantasma.Estado getEstado() {
        return estado;
    }

    // Metodo por el cual le paso el estado anterior y el actual quiero  cambiar
    // Sino puedo devuelvo false
    private Boolean puedoCambiarEstado(Estado newEstado, Estado oldEstado, Observador observer) {
        if (this.estado.equals(oldEstado)) {
            actualizarEstado(newEstado);
            notificarEstado(observer, newEstado);
            return true;
        }
        return false;
    }

    private void notificarEstado(Observador observer, Estado estado) {
        switch (estado) {
            case ATACANDO:
                observer.notificar(StateNotification.NORMAL);
                break;
            case COMIDO:
                observer.notificar(StateNotification.MUERTO);
                break;
            case HUYENDO:
                observer.notificar(StateNotification.AFECTADO);
                break;
            case ENJAULADO:
                observer.notificar(StateNotification.NORMAL);
                break;
        }
    }

    private void atacando(ServicioJuego servicio) {
        fantasma.atacar(servicio);
    }

    private void huyendo(ServicioJuego servicio) {
        fantasma.vivirHuyendo(servicio, servicio.getPacman());
    }

    private void comido(ServicioJuego servicio) {
        fantasma.vivirComido(servicio);
    }
//    private void caminoAJaula(ServicioJuego servicio) {
//        fantasma.vivirComido();
//    }
}
